package pw.hais.utils_lib.utils

import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import pw.hais.utils_lib.app.App
import java.util.*

/**
 * <pre>
 * author: Blankj
 * blog  : http://blankj.com
 * time  : 2016/08/02
 * desc  : App相关工具类
</pre> *
 */
object AppUtils {

    /**
     * 封装App信息的Bean类
     */
    class AppInfo(var packageName: String? = null,
                  var name: String? = null,
                  var icon: Drawable? = null,
                  var packagePath: String? = null,
                  var versionName: String? = null,
                  var versionCode: Int? = null,
                  var isSystem: Boolean = false)


    /**
     * 判断App是否安装
     *
     * @param packageName 包名
     * @return `true`: 已安装<br></br>`false`: 未安装
     */
    fun isInstallApp(packageName: String): Boolean {
        return App.context?.packageManager?.getLaunchIntentForPackage(packageName) != null
    }

    /**
     * 静默卸载App
     *
     * 非root需添加权限 `<uses-permission android:name="android.permission.DELETE_PACKAGES" />`
     *
     * @param packageName 包名
     * @param isKeepData  是否保留数据
     * @return `true`: 卸载成功<br></br>`false`: 卸载失败
     */
    fun uninstallAppSilent(packageName: String, isKeepData: Boolean): Boolean {
        val command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm uninstall " + (if (isKeepData) "-k " else "") + packageName
        val (_, successMsg) = ShellUtils.execCmd(command, true, true)
        return successMsg.toLowerCase().contains("success")
    }

    /**
     * 获取App路径
     *
     * @param packageName 包名
     * @return App路径
     */
    fun getAppPath(packageName: String): String? {
        return try {
            val pi = App.context?.packageManager?.getPackageInfo(packageName, 0)
            pi?.applicationInfo?.sourceDir
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            null
        }

    }

    /**
     * 获取App版本号
     *
     * @param packageName 包名
     * @return App版本号
     */
    fun getAppVersionName(packageName: String): String? {
        return try {
            val pi = App.context?.packageManager?.getPackageInfo(packageName, 0)
            pi?.versionName
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            null
        }

    }


    /**
     * 获取App版本码
     *
     * @param packageName 包名
     * @return App版本码
     */
    fun getAppVersionCode(packageName: String): Int {
        return try {
            val pi = App.context?.packageManager?.getPackageInfo(packageName, 0)
            pi?.versionCode ?: -1
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            -1
        }

    }


    /**
     * 判断App是否是系统应用
     *
     * @param packageName 包名
     * @return `true`: 是<br></br>`false`: 否
     */
    fun isSystemApp(packageName: String): Boolean {
        return try {
            val ai = App.context?.packageManager?.getApplicationInfo(packageName, 0)
            ai != null && ai.flags and ApplicationInfo.FLAG_SYSTEM != 0
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            false
        }

    }

    /**
     * 获取App信息
     *
     * AppInfo（名称，图标，包名，版本号，版本Code，是否系统应用）
     *
     * @return 当前应用的AppInfo
     */
    val appInfo: AppInfo?
        get() = getAppInfo(App.context?.packageName!!)

    /**
     * 获取App信息
     *
     * AppInfo（名称，图标，包名，版本号，版本Code，是否系统应用）
     *
     * @param packageName 包名
     * @return 当前应用的AppInfo
     */
    fun getAppInfo(packageName: String): AppInfo? {
        try {
            val pm = App.context?.packageManager
            val pi = pm?.getPackageInfo(packageName, 0)
            return getBean(pm, pi)
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            return null
        }
    }

    fun getAppInfoByFile(url: String): AppInfo? {
        try {
            val pm = App.context?.packageManager
            val pi = pm?.getPackageArchiveInfo(url, PackageManager.GET_ACTIVITIES)
            pi?.applicationInfo?.sourceDir = url
            pi?.applicationInfo?.publicSourceDir = url
            return getBean(pm, pi)
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
            return null
        }
    }

    /**
     * 得到AppInfo的Bean
     *
     * @param pm 包的管理
     * @param pi 包的信息
     * @return AppInfo类
     */
    private fun getBean(pm: PackageManager?, pi: PackageInfo?): AppInfo? {
        if (pm == null || pi == null) return null
        val ai = pi.applicationInfo
        val packageName = pi.packageName
        val name = pi.applicationInfo.loadLabel(pm).toString()
        val icon = ai.loadIcon(pm)
        val packagePath = ai.sourceDir
        val versionName = pi.versionName
        val versionCode = pi.versionCode
        val isSystem = ApplicationInfo.FLAG_SYSTEM and ai.flags != 0
        return AppInfo(packageName, name, icon, packagePath, versionName, versionCode, isSystem)
    }

    /**
     * 获取所有已安装App信息
     *
     * [.getBean]（名称，图标，包名，包路径，版本号，版本Code，是否系统应用）
     *
     * 依赖上面的getBean方法
     *
     * @return 所有已安装的AppInfo列表
     */
    fun getAppsInfo(isGetSystemApp: Boolean): MutableList<AppInfo> {
        val list = ArrayList<AppInfo>()
        val pm = App.context?.packageManager
        // 获取系统中安装的所有软件信息
        val installedPackages = pm?.getInstalledPackages(0)!!
        for (pi in installedPackages) {
            val ai = getBean(pm, pi) ?: continue
            if (!isGetSystemApp && isSystemApp(pi.packageName)) continue
            list.add(ai)
        }
        return list
    }
}
